<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>

        //1 反转给定的字符串:使用了散布运算符（…），Array的reverse方法和String的join方法来。
        const reverseString = string => [...string].reverse().join("");

        console.log(reverseString("Medium"));   //muidel 


        console.log(reverseString("Better Programming")); //gnimmargorP retteB



        // 2要计算给定数字的阶乘，我们使用箭头函数和嵌套三元运算符。 数字的m³计算
        const factorialofNumber = number =>
            number < 0
                ? (() => {

                    throw new TypeError("No negative numbers please")
                })()

                : number <= 1
                    ? 1
                    : number * factorialofNumber(number - 1)

        console.log(factorialofNumber(4));// 24
        console.log(factorialofNumber(8));// 40320



        //  3 将数字转换为数字数组
        const convertToArray = number =>
            [...`${number}`].map(el => parseInt(el))

        console.log(convertToArray(5678));//[5,6,7,8]
        console.log(convertToArray(123456789));//[1,2,3,4,5,6,7,8,9]




        // 4  检查数字是否为2的幂
        const isNumberPowerOfTwo = number => !!number && (number & (number - 1)) == 0;
        // EXAMPLES 
        console.log(isNumberPowerOfTwo(100));// false 
        console.log(isNumberPowerOfTwo(128));// true


        // 5 从对象创建键 - 值对数组
        const keyvaluePairsToArray = object => Object.keys(object)
            .map(el => [el, object[el]]);

        console.log(keyvaluePairsToArray({ Better: 4, Programming: 2 }));
        //   ["Better", 4]  ["Programming", 2]

        console.log(keyvaluePairsToArray({ x: 1, y: 2, z: 3 }));
        //    ["x", 1] ["y", 2] ["z", 3]


        //  6、从数组中返回[Number]个最大元素
        const maxElementsFromArray = (array, number = 1) => [...array].sort((x, y) => y - x).slice(0, number);
        console.log(maxElementsFromArray([1, 2, 3, 4, 51]));//[51]
        console.log(maxElementsFromArray([7, 8, 9, 10, 101, 2]));//[101]



        // 7、检查数组中的所有元素是否相等
        const elementsAreEqual = array => array.every(el => el === array[0]);
        console.log(elementsAreEqual([9, 8, 7, 6, 5]));//false
        console.log(elementsAreEqual([4, 4, 4, 4, 4]));// true


        // 8、返回两个数的平均值

        const averageOfTwoNumbers = (...numbers) => numbers.reduce((accumulator, currentvalue) =>
            accumulator + currentvalue, 0) / numbers.length

        console.log(averageOfTwoNumbers(...[6, 7, 8]));//7
        console.log(averageOfTwoNumbers(6, 87, 8));//33.666666666666664



        // 9、返回两个或多个数字的和
        const sumofNumbers = (...array) => [...array].reduce((accumulator,
            currentvalue) => accumulator + currentvalue, 0);


        console.log(sumofNumbers(5, 6, 7, 8, 9, 10));//45
        console.log(sumofNumbers(...[1, 2, 3, 4, 6, 7, 8, 9, 101])); // 141

        //10  返回数字数组的幂集

        const powersetofArray = array => array.reduce((accumulator,
            currentvalue) => accumulator.concat(accumulator.map(el => [currentvalue].concat(el))), [[]]);
            
        console.log(powersetofArray([4, 2]));//: [],  [4],[2],  [2, 4]  
        console.log(powersetofArray([1, 2, 3]));
             /*  []
            [1]
            [2]
            (2)[2, 1]
            [3]
            (2)[3, 1]
            (2)[3, 2]
            (3)[3, 2, 1] */

        /* 11  使用 Fisher–Yates shuffle 洗牌算法对数组的内容进行随机排序，生成新的数组。
        这个算法生成的随机排列是等概率的。同时这个算法非常高效。 */
        const shuffle = ([...arr]) => {
            let m = arr.length;
            while (m) {
                const i = Math.floor(Math.random() * m--);
                [arr[m], arr[i]] = [arr[i], arr[m]];
            }
            return arr;
        };

        const foo = [1, 2, 3];
        shuffle(foo); // [2, 3, 1], foo = [1, 2, 3]

        /* 12 similarity 查找两个数组之间的交集。*/
        const similarity = (arr, values) => arr.filter(v => values.includes(v));

        similarity([1, 2, 3], [1, 2, 4]); // [1, 2]

        /* 13 sleep  用于延迟异步函数的执行。 */
        const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

        async function sleepyWork() {
            console.log("I'm going to sleep for 1 second.");
            await sleep(1000);
            console.log('I woke up after 1 second.');
        }

        /* 14 smoothScroll  此段代码用于让指定的DOM节点平滑滚动到可视区域。 */

        const smoothScroll = element =>
            document.querySelector(element).scrollIntoView({
                behavior: 'smooth'
            });

        smoothScroll('#fooBar');
        // scrolls smoothly to the element with the id fooBar
        smoothScroll('.fooBar');
        // scrolls smoothly to the first element with a class of fooBar

        /* 15 sortCharactersInString   此段代码将单词的内容按照字母的顺序进行重新排序。 */
        const sortCharactersInString = str => [...str].sort((a, b) => a.localeCompare(b)).join('');

        sortCharactersInString('cabbage');
        // 'aabbceg'

        /* 16 splitLines  用于将一段字符串按照”换行符“分割成数组进行输出。*/
        const splitLines = str => str.split(/\r?\n/);
        splitLines('This\nis a\nmultiline\nstring.\n');
        // ['This', 'is a', 'multiline', 'string.' , '']

        /* 17 tripHTMLTags  格式化去掉 HTML 代码内容，输出文本内容。 */
        const stripHTMLTags = str => str.replace(/<[^>]*>/g, '');

        stripHTMLTags('<p><em>lorem</em> <strong>ipsum</strong></p>');
        // 'lorem ipsum'

        /*  17  sum 用于计算数字之和。*/
        const sum = (...arr) => [...arr].reduce((acc, val) => acc + val, 0);

        sum(1, 2, 3, 4); // 10
        sum(...[1, 2, 3, 4]); // 10

        /* 18 tail 用于获取数组除第一个元素之外的所有元素，如果数组只有一个元素，则返回本数组。*/
        const tail = arr => (arr.length > 1 ? arr.slice(1) : arr);

        tail([1, 2, 3]); // [2,3]
        tail([1]); // [1]

        /*18  take  从数组开始位置截取n个元素，生成新的数组。*/
        const take = (arr, n = 1) => arr.slice(0, n);

        take([1, 2, 3], 5); // [1, 2, 3]
        take([1, 2, 3], 0); // []

        /* 19 takeRight  从数组开始末尾截取n个元素，生成新的数组。*/
        const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length);

        takeRight([1, 2, 3], 2); // [ 2, 3 ]
        takeRight([1, 2, 3]); // [3]

        /*20 timeTaken 用来计算函数执行的时间。*/
        const timeTaken = callback => {
            console.time('timeTaken');
            const r = callback();
            console.timeEnd('timeTaken');
            return r;
        };

        timeTaken(() => Math.pow(2, 10));
        // 1024, (logged): timeTaken: 0.02099609375ms

        /*  21 times 按照指定的次数，进行回调函数。*/
        const times = (n, fn, context = undefined) => {
            let i = 0;
            while (fn.call(context, i) !== false && ++i < n) { }
        };

        var output = '';
        times(5, i => (output += i));
        console.log(output); // 01234

        /* 22 toCurrency 用于按照指定的货币类型格式化货币数字。*/
        const toCurrency = (n, curr, LanguageFormat = undefined) =>
        Intl.NumberFormat(LanguageFormat, { style: 'currency', currency: curr }).format(n);

        toCurrency(123456.789, 'EUR');
        // €123,456.79  | currency: Euro | currencyLangFormat: Local
        toCurrency(123456.789, 'USD', 'en-us');
        // $123,456.79  | currency: US Dollar | currencyLangFormat: English (United States)
        toCurrency(123456.789, 'USD', 'fa');
        // ۱۲۳٬۴۵۶٫۷۹ ؜$ | currency: US Dollar | currencyLangFormat: Farsi
        toCurrency(322342436423.2435, 'JPY');
        // ¥322,342,436,423 | currency: Japanese Yen | currencyLangFormat: Local
        toCurrency(322342436423.2435, 'JPY', 'fi');
        // 322 342 436 423 ¥ | currency: Japanese Yen | currencyLangFormat: Finnish

        /* 23 toDecimalMark 用于格式化数字，将其转换成逗号分隔的数字字符串。*/
        const toDecimalMark = num => num.toLocaleString('en-US');

        toDecimalMark(12305030388.9087);
        // "12,305,030,388.909"

        /* 24 toggleClass 使用 element.classList.toggle() 来切换元素中指定样式类。 */
        const toggleClass = (el, className) => el.classList.toggle(className);

        toggleClass(document.querySelector('p.special'), 'special');
        // The paragraph will not have the 'special' class anymore

        /* 25 tomorrow 用于获取明天的日期。*/
        const tomorrow = () => {
            let t = new Date();
            t.setDate(t.getDate() + 1);
            return t.toISOString().split('T')[0];
        };

        tomorrow();
        // 2019-09-08 (if current date is 2018-09-08)

        /* 26 unfold 基于初始值，和步长生成一个新的数组。*/
        const unfold = (fn, seed) => {
            let result = [],
                val = [null, seed];
            while ((val = fn(val[1]))) result.push(val[0]);
            return result;
        };

        var f = n => (n > 50 ? false : [-n, n + 10]);
        unfold(f, 10);
        // [-10, -20, -30, -40, -50]

        /* 27 union  合并两个数组，并删除重复的内容。*/
        const union = (a, b) => Array.from(new Set([...a, ...b]));
        union([1, 2, 3], [4, 3, 2]);
        // [1,2,3,4]

        /* 28 uniqueElements 使用 ES6 的 set 和 …rest 运算去除数组中重复的元素。*/
        const uniqueElements = arr => [...new Set(arr)];

        uniqueElements([1, 2, 2, 3, 4, 4, 5]);
        // [1, 2, 3, 4, 5]

        /* 29 validateNumber 用于检查参数类型是否是数字。 */
        const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n;

        validateNumber('10'); // true

        /* 30 words 将一段英文字符串拆分成单词数组（去除一些特殊符号）。*/
        const words = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean);

        words('I love javaScript!!');
        // ["I", "love", "javaScript"]
        words('python, javaScript & coffee');
        // ["python", "javaScript", "coffee"]

        /* 31 minN  输出数组中前 n 位最小的数。*/
        const minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n);

        minN([1, 2, 3]); // [1]
        minN([1, 2, 3], 2); // [1,2]

        /* 32 negate  将不满足函数条件的内容筛选出来。 */
        const negate = func => (...args) => !func(...args);

        [1, 2, 3, 4, 5, 6].filter(negate(n => n % 2 === 0)); // [ 1, 3, 5 ]

        /* 33 nodeListToArray  此函数返回给定的DOM节点，并以数组的形式输出。*/
        const nodeListToArray = nodeList => [...nodeList];

        nodeListToArray(document.childNodes); // [ <!DOCTYPE html>, html ]

        /* 34 pad 按照指定的长度生成字符串，如果字符串不够，
        可以按照设定的字符串内容在左右两边进行填充，默认空格为填充字符。 */

        const pad = (str, length, char = ' ') =>
            str.padStart((str.length + length) / 2, char).padEnd(length, char);

        pad('cat', 8); // '  cat   '
        pad(String(42), 6, '0'); // '004200'
        pad('foobar', 3); // 'foobar'

        /* 35 radsToDegrees 此函数功能将弧度转换成度数。 */
        const radsToDegrees = rad => (rad * 180.0) / Math.PI;

        radsToDegrees(Math.PI / 2); // 90

        /* 36 randomHexColorCode 此段代码用于生成随机的16进制颜色代码。*/
        const randomHexColorCode = () => {
            let n = (Math.random() * 0xfffff * 1000000).toString(16);
            return '#' + n.slice(0, 6);
        };

        randomHexColorCode(); // "#e34155"

        /* 37 randomIntArrayInRange  按照指定的数字范围随机生成长度为 n 的数组。*/
        const randomIntArrayInRange = (min, max, n = 1) =>
            Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1)) + min);

        randomIntArrayInRange(12, 35, 10); // [ 34, 14, 27, 17, 30, 27, 20, 26, 21, 14 ]

        /* 38 randomIntegerInRange 按照指定的范围内生成一个随机整数。 */
        const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;

        randomIntegerInRange(0, 5); // 3

        /* 39 randomNumberInRange 该代码段可用于返回指定范围内的随机数（包含小数部分）。 */
        const randomNumberInRange = (min, max) => Math.random() * (max - min) + min;

        randomNumberInRange(2, 10); // 6.0211363285087005

        /* 40 readFileLines 此段代码将读取到的文本内容，按行分割组成数组进行输出。 */
        const fs = require('fs');
        const readFileLines = filename =>
            fs
            .readFileSync(filename)
            .toString('UTF8')
            .split('\n');

        let arr = readFileLines('test.txt');
        console.log(arr); // ['line1', 'line2', 'line3']

        /* 41 Redirect to a URL 此函数功能将页面导向一个指定的网站地址。 */
        const redirect = (url, asLink = true) =>
            asLink ? (window.location.href = url) : window.location.replace(url);

        redirect('https://www.qianduandaren.com');

        /* 42 reverse 此段代码用于将一段字符串进行颠倒。 */
        const reverseString = str => [...str].reverse().join('');

        reverseString('foobar'); // 'raboof'

        /* 42 round 将小数按照指定的位数，进行四舍五入保留。 */
        const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);

        round(1.005, 2); // 1.01

        /* 43 runPromisesInSeries 通过数组的形式，连续运行多个promise。 */
        const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());
        const delay = d => new Promise(r => setTimeout(r, d));

        runPromisesInSeries([() => delay(1000), () => delay(2000)]);
        // Executes each promise sequentially, taking a total of 3 seconds to complete

        /* 44 sample  从数组中获取一个随机数。*/
        const sample = arr => arr[Math.floor(Math.random() * arr.length)];

        sample([3, 7, 9, 11]); // 9

        /* 45 sampleSize 在数组中随机生选择 n 个元素生成新的数组，
        如果n大于数组长度，则为随机整个数组的排序。
        这里使用到了 Fisher–Yates shuffle 洗牌算法。
        简单来说 Fisher–Yates shuffle 
        算法是一个用来将一个有限集合生成一个随机排列的算法（数组随机排序）。
        这个算法生成的随机排列是等概率的。同时这个算法非常高效。 */

        const sampleSize = ([...arr], n = 1) => {
            let m = arr.length;
            while (m) {
                const i = Math.floor(Math.random() * m--);
                [arr[m], arr[i]] = [arr[i], arr[m]];
            }
            return arr.slice(0, n);
        };

        sampleSize([1, 2, 3], 2); // [3,1]
        sampleSize([1, 2, 3], 4); // [2,3,1]

        /* 46 scrollToTop 此函数功能将页面平滑的滚动到页面的顶部。 */
        const scrollToTop = () => {
            const c = document.documentElement.scrollTop || document.body.scrollTop;
            if (c > 0) {
                window.requestAnimationFrame(scrollToTop);
                window.scrollTo(0, c - c / 8);
            }
        };

        scrollToTop();

        /* 47 serializeCookie 段代码用于将 cookie 序列化成 name-value 的形式方便你
        存储在 Set-Cookie 头信息里。 */
        const serializeCookie = (name, val) => `${encodeURIComponent(name)}=${encodeURIComponent(val)}`;

        serializeCookie('foo', 'bar'); // 'foo=bar

        /* 48 serializeCookie 此段代码用于在相应的DOM节点添加属性和值。 */
        const setStyle = (el, ruleName, val) => (el.style[ruleName] = val);

        setStyle(document.querySelector('p'), 'font-size', '20px');
        // The first <p> element on the page will have a font-size of 20px

        /* 49 shallowClone 此段代码用于浅复制一个对象。  */
        const shallowClone = obj => Object.assign({}, obj);

        const a = { x: true, y: 1 };
        const b = shallowClone(a); // a !== b

        /* 50 show  从段代码用于显示所有指定的 DOM 元素。*/

        const show = (...el) => [...el].forEach(e => (e.style.display = ''));

        show(...document.querySelectorAll('img')); // Shows all <img> elements on the page


        /* 51 getColonTimeFromDate  用于判断程序运行环境是否在浏览器，这有助于避免在node环境运行前端模块时出错。*/
        const isBrowser = () => ![typeof window, typeof document].includes('undefined');

        isBrowser(); // true (browser)
        isBrowser(); // false (Node)

        /* 52 isBrowserTabFocused 用于判断当前页面是否处于活动状态（显示状态）。 */
        const isBrowserTabFocused = () => !document.hidden;
        isBrowserTabFocused(); // true
        

        /* 53 isLowerCase 用于判断当前字符串是否都为小写。 */
        const isLowerCase = str => str === str.toLowerCase();

        isLowerCase('abc'); // true
        isLowerCase('a3@$'); // true
        isLowerCase('Ab4'); // false

        /* 54 isNil  用于判断当前变量的值是否为 null 或 undefined 类型。*/
        const isNil = val => val === undefined || val === null;

        isNil(null); // true
        isNil(undefined); // true

        /* 55 isNull 用于判断当前变量的值是否为 null 类型 */

        const isNull = val => val === null;

        isNull(null); // true

        /* 56 isNumber 用于检查当前的值是否为数字类型 */
        function isNumber(n) {
            return !isNaN(parseFloat(n)) && isFinite(n);
        }

        isNumber('1'); // false
        isNumber(1); // true

        /* 57  isObject 用于判断参数的值是否是对象，
        这里运用了Object 构造函数创建一个对象包装器，如果是对象类型，将会原值返回。 */
        const isObject = obj => obj === Object(obj);

        isObject([1, 2, 3, 4]); // true
        isObject([]); // true
        isObject(['Hello!']); // true
        isObject({ a: 1 }); // true
        isObject({}); // true
        isObject(true); // false

        /* 58 isObjectLike 用于检查参数的值是否为null以及类型是否为对象。 */
        const isObjectLike = val => val !== null && typeof val === 'object';

        isObjectLike({}); // true
        isObjectLike([1, 2, 3]); // true
        isObjectLike(x => x); // false
        isObjectLike(null); // false

        /*59 isPlainObject  用于检查当前的对象是否类似Promise函数。*/
        const isPromiseLike = obj =>
            obj !== null &&
            (typeof obj === 'object' || typeof obj === 'function') &&
            typeof obj.then === 'function';

        isPromiseLike({
            then: function () {
                return '';
            }
        }); // true
        isPromiseLike(null); // false
        isPromiseLike({}); // false

        /* 60 isSameDate 用于判断给定的两个日期是否是同一天。 */
        const isSameDate = (dateA, dateB) => dateA.toISOString() === dateB.toISOString();

        isSameDate(new Date(2010, 10, 20), new Date(2010, 10, 20)); // true

        /* 61 isString  用于检查当前的值是否为字符串类型。*/
        const isString = val => typeof val === 'string';

        isString('10'); // true

        /* 62 isSymbol 用于判断参数的值是否是 Symbol 类型。 */

        const isSymbol = val => typeof val === 'symbol';

        isSymbol(Symbol('x')); // true

        /* 63 isUndefined 用于判断参数的类型是否是 Undefined 类型。 */
        const isUndefined = val => val === undefined;

        isUndefined(undefined); // true


        /* 64  isUpperCase 用于判断当前字符串的字母是否都为大写。 */
        const isUpperCase = str => str === str.toUpperCase();

        isUpperCase('ABC'); // true
        isLowerCase('A3@$'); // true
        isLowerCase('aB4'); // false

        /* 65 isValidJSON 用于判断给定的字符串是否是 JSON 字符串。 */
        const isValidJSON = str => {
            try {
                JSON.parse(str);
                return true;
            } catch (e) {
                return false;
            }
        };

        isValidJSON('{"name":"Adam","age":20}'); // true
        isValidJSON('{"name":"Adam",age:"20"}'); // false
        isValidJSON(null); // true

        /* 66 last 此函数功能返回数组的最后一个元素。 */
        const last = arr => arr[arr.length - 1];

        last([1, 2, 3]); // 3


        /* 67 matches 此函数功能用于比较两个对象，以确定第一个对象是否包含与第二个对象相同的属性值。 */
        const matches = (obj, source) =>
            Object.keys(source).every(key => obj.hasOwnProperty(key) && obj[key] === source[key]);

        matches({ age: 25, hair: 'long', beard: true }, { hair: 'long', beard: true }); // true
        matches({ hair: 'long', beard: true }, { age: 25, hair: 'long', beard: true }); // false

        /* 68 maxDate 此代码段查找日期数组中最大的日期进行输出。 */
        const maxDate = (...dates) => new Date(Math.max.apply(null, ...dates));

        const array = [
            new Date(2017, 4, 13),
            new Date(2018, 2, 12),
            new Date(2016, 0, 10),
            new Date(2016, 0, 9)
        ];
        maxDate(array); // 2018-03-11T22:00:00.000Z

        /* 69 maxN 此段代码输出数组中前 n 位最大的数。 */
        const maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n);

        maxN([1, 2, 3]); // [3]
        maxN([1, 2, 3], 2); // [3,2]


        /* 70 minDate  此代码段查找日期数组中最早的日期进行输出。*/
        const minDate = (...dates) => new Date(Math.min.apply(null, ...dates));

        const array = [
            new Date(2017, 4, 13),
            new Date(2018, 2, 12),
            new Date(2016, 0, 10),
            new Date(2016, 0, 9)
        ];
        minDate(array); // 2016-01-08T22:00:00.000Z


        /* 71 getColonTimeFromDate 此段代码从Date对象里获取当前时间。 */
        const getColonTimeFromDate = date => date.toTimeString().slice(0, 8);
        getColonTimeFromDate(new Date()); // "08:38:00"


        /* 72 getDaysDiffBetweenDates 此段代码返回两个日期之间相差多少天 */
        const getDaysDiffBetweenDates = (dateInitial, dateFinal) =>
            (dateFinal - dateInitial) / (1000 * 3600 * 24);

        getDaysDiffBetweenDates(new Date('2019-01-13'), new Date('2019-01-15')); // 2

        /* 73 getStyle 此代码返回DOM元素节点对应的属性值。 */
        const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName];

        getStyle(document.querySelector('p'), 'font-size'); // '16px'

        /* 74 getType 此段代码的主要功能就是返回数据的类型。 */

        const getType = v =>
            v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase();

        getType(new Set([1, 2, 3])); // 'set'


        /* 75 hasClass 此段代码返回DOM元素是否包含指定的Class样式。 */

        const hasClass = (el, className) => el.classList.contains(className);
        hasClass(document.querySelector('p.special'), 'special'); // true
        
        /*  76、head  此段代码输出数组的第一个元素。 */

        const head = arr => arr[0];

        head([1, 2, 3]); // 1


        /* 77、hide  此段代码隐藏指定的DOM元素。 */

        const hide = (...el) => [...el].forEach(e => (e.style.display = 'none'));

        hide(document.querySelectorAll('img')); // Hides all <img> elements on the page
        
        
       /*  78、httpsRedirect 此段代码的功能就是将http网址重定向https网址。*/
        const httpsRedirect = () => {
            if (location.protocol !== 'https:') location.replace('https://' + location.href.split('//')[1]);
        };

        httpsRedirect(); // If you are on http://mydomain.com, you are redirected to https://mydomain.com
        
        
        /* 79、indexOfAll 此代码可以返回数组中某个值对应的所有索引值，
        如果不包含该值，则返回一个空数组。 */

        const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []);

        indexOfAll([1, 2, 3, 1, 2, 3], 1); // [0,3]
        indexOfAll([1, 2, 3], 4); // []


       /*  80、initial  此段代码返回数组中除最后一个元素的所有元素 */

        const initial = arr => arr.slice(0, -1);

        initial([1, 2, 3]); // [1,2]const initial = arr => arr.slice(0, -1);
        initial([1, 2, 3]); // [1,2]
        
        
        /* 81、insertAfter此段代码的功能主要是在给定的DOM节点后插入新的节点内容 */

        const insertAfter = (el, htmlString) => el.insertAdjacentHTML('afterend', htmlString);

        insertAfter(document.getElementById('myId'), '<p>after</p>'); // <div id="myId">...</div> <p>after</p>
        
        /* 82、insertBefore 此段代码的功能主要是在给定的DOM节点前插入新的节点内容 */

        const insertBefore = (el, htmlString) => el.insertAdjacentHTML('beforebegin', htmlString);

        insertBefore(document.getElementById('myId'), '<p>before</p>'); // <p>before</p> <div id="myId">...</div>
        
        /* 83、intersection 此段代码返回两个数组元素之间的交集。 */

        const intersection = (a, b) => {
            const s = new Set(b);
            return a.filter(x => s.has(x));
        };

        intersection([1, 2, 3], [4, 3, 2]); // [2, 3]
       /*  84、intersectionBy按照给定的函数处理需要对比的数组元素，
       然后根据处理后的数组，找出交集，最后从第一个数组中将对应的元素输出。 */

        const intersectionBy = (a, b, fn) => {
            const s = new Set(b.map(fn));
            return a.filter(x => s.has(fn(x)));
        };

        intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor); // [2.1]
        
        
        /* 85、intersectionBy 按照给定的函数对比两个数组的差异，
        然后找出交集，最后从第一个数组中将对应的元素输出。 */

        const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, y)) !== -1);

        intersectionWith([1, 1.2, 1.5, 3, 0], [1.9, 3, 0, 3.9], (a, b) => Math.round(a) === Math.round(b)); // [1.5, 3, 0]
       
       
       /*  86、is 此段代码用于判断数据是否为指定的数据类型，如果是则返回true。 */

        const is = (type, val) => ![, null].includes(val) && val.constructor === type;

        is(Array, [1]); // true
        is(ArrayBuffer, new ArrayBuffer()); // true
        is(Map, new Map()); // true
        is(RegExp, /./g); // true
        is(Set, new Set()); // true
        is(WeakMap, new WeakMap()); // true
        is(WeakSet, new WeakSet()); // true
        is(String, ''); // true
        is(String, new String('')); // true
        is(Number, 1); // true
        is(Number, new Number(1)); // true
        is(Boolean, true); // true
        is(Boolean, new Boolean(true)); // true
        
        
        /* 87、isAfterDate 接收两个日期类型的参数，判断前者的日期是否晚于后者的日期。 */

        const isAfterDate = (dateA, dateB) => dateA > dateB;

        isAfterDate(new Date(2010, 10, 21), new Date(2010, 10, 20)); // true
        
        
        
        /* 88、isAnagram 用于检测两个单词是否相似。 */

        const isAnagram = (str1, str2) => {
            const normalize = str =>
                str
                    .toLowerCase()
                    .replace(/[^a-z0-9]/gi, '')
                    .split('')
                    .sort()
                    .join('');
            return normalize(str1) === normalize(str2);
        };

        isAnagram('iceman', 'cinema'); // true
        
        
        /* 89、isArrayLike 此段代码用于检测对象是否为类数组对象, 是否可迭代。 */

        const isArrayLike = obj => obj != null && typeof obj[Symbol.iterator] === 'function';

        isArrayLike(document.querySelectorAll('.className')); // true
        isArrayLike('abc'); // true
        isArrayLike(null); // false
        
        
        /* 90、isBeforeDate 接收两个日期类型的参数，判断前者的日期是否早于后者的日期。 */

        const isBeforeDate = (dateA, dateB) => dateA < dateB;

        isBeforeDate(new Date(2010, 10, 20), new Date(2010, 10, 21)); // true
       
       
        /*  91、isBoolean 此段代码用于检查参数是否为布尔类型。*/
        const isBoolean = val => typeof val === 'boolean';

        isBoolean(null); // false
        isBoolean(false); // true



        /* 92、deepFlatten 通过递归的形式，将多维数组展平成一维数组。*/
 
        const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)));

        deepFlatten([1, [2], [[3], 4], 5]); // [1,2,3,4,5]


       /*  93、default 去重对象的属性，如果对象中含有重复的属性，以前面的为准。 */

        const defaults = (obj, ...defs) => Object.assign({}, obj, ...defs.reverse(), obj);

        defaults({ a: 1 }, { b: 2 }, { b: 6 }, { a: 3 }); // { a: 1, b: 2 }
        
        
        /* 94、defer 延迟函数的调用，即异步调用函数。 */

        const defer = (fn, ...args) => setTimeout(fn, 1, ...args);

        defer(console.log, 'a'), console.log('b'); // logs 'b' then 'a'
       
       /* 95、degreesToRads 此段代码将标准的度数，转换成弧度。 */

        const degreesToRads = deg => (deg * Math.PI) / 180.0;

        degreesToRads(90.0); // ~1.5708
       
       
       /*  96、difference 此段代码查找两个给定数组的差异，查找出前者数组在后者数组中不存在元素。 */

        const difference = (a, b) => {
            const s = new Set(b);
            return a.filter(x => !s.has(x));
        };

        difference([1, 2, 3], [1, 2, 4]); // [3]
        
        /* 97、differenceBy通过给定的函数来处理需要对比差异的数组，查找出前者数组在后者数组中不存在元素。 */

        const differenceBy = (a, b, fn) => {
            const s = new Set(b.map(fn));
            return a.filter(x => !s.has(fn(x)));
        };

        differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); // [1.2]
        differenceBy([{ x: 2 }, { x: 1 }], [{ x: 1 }], v => v.x); // [ { x: 2 } ]
        
        
        /* 98、differenceWith 此段代码按照给定函数逻辑筛选需要对比差异的数组，查找出前者数组在后者数组中不存在元素。 */

        const differenceWith = (arr, val, comp) => arr.filter(a => val.findIndex(b => comp(a, b)) === -1);

        differenceWith([1, 1.2, 1.5, 3, 0], [1.9, 3, 0], (a, b) => Math.round(a) === Math.round(b));
        // [1, 1.2]


        /* 99、digitize 将输入的数字拆分成单个数字组成的数组。 */

        const digitize = n => [...`${n}`].map(i => parseInt(i));

        digitize(431); // [4, 3, 1]
        
        /* 100、distance 计算两点之间的距离 */

        const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);

        distance(1, 1, 2, 3); // 2.23606797749979
        
        /* 101、drop 此段代码将给定的数组从左边开始删除 n 个元素 */

        const drop = (arr, n = 1) => arr.slice(n);

        drop([1, 2, 3]); // [2,3]
        drop([1, 2, 3], 2); // [3]
        drop([1, 2, 3], 42); // []
        
        /* 102、dropRight此段代码将给定的数组从右边开始删除 n 个元素 */

        const dropRight = (arr, n = 1) => arr.slice(0, -n);

        dropRight([1, 2, 3]); // [1,2]
        dropRight([1, 2, 3], 2); // [1]
        dropRight([1, 2, 3], 42); // []
        
        
        /* 103、dropRightWhile
        此段代码将给定的数组按照给定的函数条件从右开始删除，
        直到当前元素满足函数条件为True时，停止删除，并返回数组剩余元素。 */

        const dropRightWhile = (arr, func) => {
            while (arr.length > 0 && !func(arr[arr.length - 1])) arr = arr.slice(0, -1);
            return arr;
        };

        dropRightWhile([1, 2, 3, 4], n => n < 3); // [1, 2]
        
        
        /* 104、dropWhile按照给的的函数条件筛选数组，不满足函数条件的将从数组中移除。 */

        const dropWhile = (arr, func) => {
            while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1);
            return arr;
        };

        dropWhile([1, 2, 3, 4], n => n >= 3); // [3,4]
        
        
        /* 105、elementContains 接收两个DOM元素对象参数，判断后者是否是前者的子元素。 */

        const elementContains = (parent, child) => parent !== child && parent.contains(child);

        elementContains(document.querySelector('head'), document.querySelector('title')); // true
        elementContains(document.querySelector('body'), document.querySelector('body')); // false
        
        
        /* 106、filterNonUnique 移除数组中重复的元素 */

        const filterNonUnique = arr => [...new Set(arr)];
        filterNonUnique([1, 2, 2, 3, 4, 4, 5]); // [1, 2, 3, 4, 5]
        
        
        /* 107、findKey 按照给定的函数条件，查找第一个满足条件对象的键值。 */

        const findKey = (obj, fn) => Object.keys(obj).find(key => fn(obj[key], key, obj));

        findKey(
            {
                barney: { age: 36, active: true },
                fred: { age: 40, active: false },
                pebbles: { age: 1, active: true }
            },
            o => o['active']
        ); // 'barney'
        
        
        /* 108、findLast 按照给定的函数条件筛选数组，将最后一个满足条件的元素进行删除。 */

        const findLast = (arr, fn) => arr.filter(fn).pop();

        findLast([1, 2, 3, 4], n => n % 2 === 1); // 3
       
       
       /*  109、flatten 按照指定数组的深度，将嵌套数组进行展平。 */

        const flatten = (arr, depth = 1) =>
            arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []);

        flatten([1, [2], 3, 4]); // [1, 2, 3, 4]
        flatten([1, [2, [3, [4, 5], 6], 7], 8], 2); // [1, 2, 3, [4, 5], 6, 7, 8]
        
        /* 110、forEachRight按照给定的函数条件，从数组的右边往左依次进行执行。 */


        const forEachRight = (arr, callback) =>
            arr
                .slice(0)
                .reverse()
                .forEach(callback);

        forEachRight([1, 2, 3, 4], val => console.log(val)); // '4', '3', '2', '1'
        /* 111、forOwn此段代码按照给定的函数条件，进行迭代对象。 */

        const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj));
        forOwn({ foo: 'bar', a: 1 }, v => console.log(v)); // 'bar', 1
        
        
        /* 122、functionName 此段代码输出函数的名称。*/
        const functionName = fn => (console.debug(fn.name), fn);

        functionName(Math.max); // max (logged in debug channel of console)


       /* 123、all 如果数组所有元素满足函数条件，则返回true。
       调用时，如果省略第二个参数，则默认传递布尔值。 */

        const all = (arr, fn = Boolean) => arr.every(fn);

        all([4, 2, 3], x => x > 1); // true
        all([1, 2, 3]); // true


        /* 124、allEqual判断数组中的元素是否都相等 */

        const allEqual = arr => arr.every(val => val === arr[0]);

        allEqual([1, 2, 3, 4, 5, 6]); // false
        allEqual([1, 1, 1, 1]); // true
        
        /* 125、approximatelyEqual
        此代码示例检查两个数字是否近似相等，差异值可以通过传参的形式进行设置 */

        const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon;

        approximatelyEqual(Math.PI / 2.0, 1.5708); // true
        
        
        /* 126 、arrayToCSV
        此段代码将没有逗号或双引号的元素转换成带有逗号分隔符的字符串即CSV格式识别的形式。 */

        const arrayToCSV = (arr, delimiter = ',') =>
            arr.map(v => v.map(x => `"${x}"`).join(delimiter)).join('\n');

        arrayToCSV([['a', 'b'], ['c', 'd']]); // '"a","b"\n"c","d"'
        arrayToCSV([['a', 'b'], ['c', 'd']], ';'); // '"a";"b"\n"c";"d"'
        
        
        /* 127、arrayToHtmlList
        此段代码将数组元素转换成 < li > 标记，并将此元素添加至给定的ID元素标记内。 */

        const arrayToHtmlList = (arr, listID) =>
            (el => (
                (el = document.querySelector('#' + listID)),
                (el.innerHTML += arr.map(item => `<li>${item}</li>`).join(''))
            ))();

        arrayToHtmlList(['item 1', 'item 2'], 'myListID');
       
        /* 128、attempt
        此段代码执行一个函数，将剩余的参数传回函数当参数，返回相应的结果，并能捕获异常。 */

        const attempt = (fn, ...args) => {
            try {
                return fn(...args);
            } catch (e) {
                return e instanceof Error ? e : new Error(e);
            }
        };
        var elements = attempt(function (selector) {
            return document.querySelectorAll(selector);
        }, '>_>');
        if (elements instanceof Error) elements = []; // elements = []
       /*  129、average 此段代码返回两个或多个数的平均数。 */

        const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length;
        average(...[1, 2, 3]); // 2
        average(1, 2, 3); // 2
        
        
        /* 130、averageBy
        一个 map()函数和 reduce()函数结合的例子，此函数先通过 map() 
        函数将对象转换成数组，然后在调用reduce()函数进行累加，然后根据数组长度返回平均值。 */

        const averageBy = (arr, fn) =>
            arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0) /
            arr.length;

        averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], o => o.n); // 5
        averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 5
        
        /* 131、bifurcate
        此函数包含两个参数，类型都为数组，依据第二个参数的真假条件，将一个参数的数组进行分组，条件为真的放入第一个数组，
        其它的放入第二个数组。这里运用了Array.prototype.reduce() 和 Array.prototype.push() 相结合的形式。 */

        const bifurcate = (arr, filter) =>
            arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]);
        bifurcate(['beep', 'boop', 'foo', 'bar'], [true, true, false, true]);
        // [ ['beep', 'boop', 'bar'], ['foo'] ]
        
        
        /* 132、bifurcateBy
        此段代码将数组按照指定的函数逻辑进行分组，满足函数条件的逻辑为真，
        放入第一个数组中，其它不满足的放入第二个数组 。这里运用了Array.prototype.reduce() 和 Array.prototype.push() 相结合的形式，基于函数过滤逻辑，通过 Array.prototype.push() 函数将其添加到数组中。 */

        const bifurcateBy = (arr, fn) =>
            arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]);

        bifurcateBy(['beep', 'boop', 'foo', 'bar'], x => x[0] === 'b');
        // [ ['beep', 'boop', 'bar'], ['foo'] ]
        
        
        /* 133、bottomVisible 用于检测页面是否滚动到页面底部。 */

        const bottomVisible = () =>
            document.documentElement.clientHeight + window.scrollY >=
            (document.documentElement.scrollHeight || document.documentElement.clientHeight);

        bottomVisible(); // true
        
        /* 134、byteSize
        此代码返回字符串的字节长度。这里用到了Blob对象，Blob（Binary Large Object）对象代表了一段二进制数据，
        提供了一系列操作接口。其他操作二进制数据的API（比如File对象），都是建立在Blob对象基础上的，继承了它的属性和方法。生成Blob对象有两种方法：一种是使用Blob构造函数，另一种是对现有的Blob对象使用slice方法切出一部分。 */

        const byteSize = str => new Blob([str]).size;

        byteSize(''); // 4
        byteSize('Hello World'); // 11
        
        /* 135、capitalize
        将字符串的首字母转成大写, 这里主要运用到了ES6的展开语法在数组中的运用。 */

        const capitalize = ([first, ...rest]) =>
            first.toUpperCase() + rest.join('');

        capitalize('fooBar'); // 'FooBar'
        capitalize('fooBar', true); // 'FooBar'
        
        /* 136、capitalizeEveryWord
        将一个句子中每个单词首字母转换成大写字母，这里中要运用了正则表达式进行替换。 */

        const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase());

        capitalizeEveryWord('hello world!'); // 'Hello World!'
        
        /* 137、castArray 此段代码将非数值的值转换成数组对象。 */

        const castArray = val => (Array.isArray(val) ? val : [val]);

        castArray('foo'); // ['foo']
        castArray([1]); // [1]
       
       
       /*  138、compact将数组中移除值为 false 的内容。 */

        const compact = arr => arr.filter(Boolean);

        compact([0, 1, false, 2, '', 3, 'a', 'e' * 23, NaN, 's', 34]);
        // [ 1, 2, 3, 'a', 's', 34 ]
       
       
       /*  139、countOccurrences
        统计数组中某个值出现的次数 */

        const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0);
        countOccurrences([1, 1, 2, 1, 2, 3], 1); // 3
        
        
        /* 140、Create Directory
        此代码段使用 existSync() 检查目录是否存在，
        然后使用 mkdirSync() 创建目录（如果不存在）。 */

        const fs = require('fs');
        const createDirIfNotExists = dir => (!fs.existsSync(dir) ? fs.mkdirSync(dir) : undefined);
        createDirIfNotExists('test');
        // creates the directory 'test', if it doesn't exist
        
        
        /* 141、currentURL
        返回当前访问的 URL 地址。*/
        const currentURL = () => window.location.href;

        currentURL(); // 'https://medium.com/@fatosmorina'
        
        
        /* 142、dayOfYear
        返回当前是今年的第几天 */

        const dayOfYear = date =>
            Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24);

        dayOfYear(new Date()); // 272
        
        
        /* 143、decapitalize
        将字符串的首字母转换成小写字母 */

        const decapitalize = ([first, ...rest]) =>
            first.toLowerCase() + rest.join('')

        decapitalize('FooBar'); // 'fooBar'
    </script>
</body>

</html>